"""
角色管理API端点
"""

from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional

from app.core.database import get_db
from app.core.dependencies import (
    get_current_active_user, require_role_view, require_role_manage
)
from app.models.auth import User
from app.schemas.auth import (
    RoleCreate, RoleUpdate, RoleResponse, RoleListResponse
)
from app.schemas.common import BaseResponse
from app.services.permission_service import PermissionService
from app.utils.timezone_utils import get_shanghai_now
from app.core.logger import logger

router = APIRouter()
permission_service = PermissionService()


@router.get("", response_model=BaseResponse[RoleListResponse])
async def get_roles(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    search: Optional[str] = Query(None, description="搜索关键词"),
    is_active: Optional[bool] = Query(None, description="角色状态"),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_role_view)
):
    """
    获取角色列表
    
    - **page**: 页码，从1开始
    - **page_size**: 每页数量，最大100
    - **search**: 搜索角色名称或显示名称
    - **is_active**: 按状态筛选
    """
    try:
        from sqlalchemy import select, and_, or_, func
        from sqlalchemy.orm import selectinload
        from app.models.auth import Role, RolePermission
        
        # 构建查询条件
        conditions = []
        
        if search:
            conditions.append(
                or_(
                    Role.name.contains(search),
                    Role.display_name.contains(search),
                    Role.description.contains(search)
                )
            )
        
        if is_active is not None:
            conditions.append(Role.is_active == is_active)
        
        # 查询总数
        count_stmt = select(func.count(Role.id))
        if conditions:
            count_stmt = count_stmt.where(and_(*conditions))
        
        result = await db.execute(count_stmt)
        total = result.scalar()
        
        # 查询角色列表
        stmt = select(Role).options(
            selectinload(Role.role_permissions).selectinload(RolePermission.permission)
        )
        
        if conditions:
            stmt = stmt.where(and_(*conditions))
        
        stmt = stmt.offset((page - 1) * page_size).limit(page_size)
        stmt = stmt.order_by(Role.created_at.desc())
        
        result = await db.execute(stmt)
        roles = result.scalars().all()
        
        return BaseResponse(
            data=RoleListResponse(
                roles=[RoleResponse.from_orm(role) for role in roles],
                total=total,
                page=page,
                page_size=page_size,
                total_pages=(total + page_size - 1) // page_size
            ),
            message="获取角色列表成功",
            success=True
        )
    except Exception as e:
        logger.error(f"获取角色列表失败：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取角色列表失败"
        )


@router.post("", response_model=BaseResponse[RoleResponse])
async def create_role(
    role_data: RoleCreate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_role_manage)
):
    """
    创建角色
    
    - **name**: 角色名称（唯一）
    - **display_name**: 角色显示名称
    - **description**: 角色描述（可选）
    - **permission_ids**: 权限ID列表（可选）
    """
    try:
        result = await permission_service.create_role(db, role_data, current_user)
        
        return BaseResponse(
            data=result,
            message="角色创建成功",
            success=True
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"创建角色失败：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="创建角色失败"
        )


@router.get("/{role_id}", response_model=BaseResponse[RoleResponse])
async def get_role(
    role_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_role_view)
):
    """
    获取角色详情
    
    - **role_id**: 角色ID
    """
    try:
        from sqlalchemy import select
        from sqlalchemy.orm import selectinload
        from app.models.auth import Role, RolePermission
        
        stmt = select(Role).where(Role.id == role_id).options(
            selectinload(Role.role_permissions).selectinload(RolePermission.permission)
        )
        result = await db.execute(stmt)
        role = result.scalar_one_or_none()
        
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )
        
        return BaseResponse(
            data=RoleResponse.from_orm(role),
            message="获取角色详情成功",
            success=True
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取角色详情失败：{str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="获取角色详情失败"
        )


@router.put("/{role_id}", response_model=BaseResponse[RoleResponse])
async def update_role(
    role_id: int,
    role_data: RoleUpdate,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_role_manage)
):
    """
    更新角色信息
    
    - **role_id**: 角色ID
    - **display_name**: 角色显示名称（可选）
    - **description**: 角色描述（可选）
    - **is_active**: 角色状态（可选）
    - **permission_ids**: 权限ID列表（可选）
    """
    try:
        from sqlalchemy import select, delete
        from sqlalchemy.orm import selectinload
        from app.models.auth import Role, RolePermission, Permission
        from datetime import datetime
        
        # 查找角色
        stmt = select(Role).where(Role.id == role_id).options(
            selectinload(Role.role_permissions).selectinload(RolePermission.permission)
        )
        result = await db.execute(stmt)
        role = result.scalar_one_or_none()
        
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )
        
        # 检查是否为系统角色
        if role.is_system and not current_user.is_superuser:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="无权修改系统角色"
            )
        
        # 更新角色信息
        update_data = role_data.dict(exclude_unset=True)
        permission_ids = update_data.pop('permission_ids', None)
        
        for field, value in update_data.items():
            setattr(role, field, value)
        
        # 更新权限分配
        if permission_ids is not None:
            # 删除现有权限分配
            stmt = delete(RolePermission).where(RolePermission.role_id == role_id)
            await db.execute(stmt)
            
            # 添加新的权限分配
            for permission_id in permission_ids:
                # 验证权限是否存在
                stmt = select(Permission).where(Permission.id == permission_id)
                result = await db.execute(stmt)
                permission = result.scalar_one_or_none()
                if not permission:
                    raise HTTPException(
                        status_code=status.HTTP_400_BAD_REQUEST,
                        detail=f"权限ID {permission_id} 不存在"
                    )
                
                role_permission = RolePermission(
                    role_id=role_id,
                    permission_id=permission_id,
                    granted_by=current_user.id,
                    granted_at=get_shanghai_now()
                )
                db.add(role_permission)

        role.updated_at = get_shanghai_now()
        await db.commit()
        
        # 重新查询角色以获取完整信息
        stmt = select(Role).where(Role.id == role_id).options(
            selectinload(Role.role_permissions).selectinload(RolePermission.permission)
        )
        result = await db.execute(stmt)
        role = result.scalar_one()
        
        logger.info(f"角色更新成功：{role.name} (by {current_user.username})")
        
        return BaseResponse(
            data=RoleResponse.from_orm(role),
            message="角色更新成功",
            success=True
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"更新角色失败：{str(e)}")
        await db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="更新角色失败"
        )


@router.delete("/{role_id}", response_model=BaseResponse[dict])
async def delete_role(
    role_id: int,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_role_manage)
):
    """
    删除角色
    
    - **role_id**: 角色ID
    """
    try:
        from sqlalchemy import select
        from app.models.auth import Role, UserRole
        
        # 查找角色
        stmt = select(Role).where(Role.id == role_id)
        result = await db.execute(stmt)
        role = result.scalar_one_or_none()
        
        if not role:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="角色不存在"
            )
        
        # 检查是否为系统角色
        if role.is_system:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="不能删除系统角色"
            )
        
        # 检查是否有用户使用此角色
        stmt = select(UserRole).where(UserRole.role_id == role_id)
        result = await db.execute(stmt)
        user_roles = result.scalars().all()
        
        if user_roles:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"角色正在被 {len(user_roles)} 个用户使用，无法删除"
            )
        
        role_name = role.name
        await db.delete(role)
        await db.commit()
        
        logger.info(f"角色删除成功：{role_name} (by {current_user.username})")
        
        return BaseResponse(
            data={"message": f"角色 {role_name} 删除成功"},
            message="角色删除成功",
            success=True
        )
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除角色失败：{str(e)}")
        await db.rollback()
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="删除角色失败"
        )
